/**************************************************************************//**
 * @file     uart.c
 * @brief    stm32f1xx uart 模块操作接口
 * @version  V0.0.1
 * @date     2020-02-01
 ******************************************************************************/
/*
 * Copyright (c) 2020, 2020 by xiao xiang. All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * is freely granted, provided that this notice is preserved.
 */
#ifndef _UART_H_
#define _UART_H_

typedef struct {
    USART_TypeDef *pUsartReg; /*!< 对应串口寄存器起始地址 */
    
    // 用户初始化配置
    EN_USART_BAUD baudRate;   /*!< 波特率 */
    EN_USART_WORD_LENGTH wordLength;  /*!< 数据长度，即寄存器M位，8B还是9B */
    EN_USART_STOP stopBits;   /*!< 停止位长度 */
    EN_USART_PARITY parity;   /*!< 是否开启奇偶校验 */
    uint32_t isEnableIrq;     /*!< Enable=使能中断模式 DISABLE=关闭中断模式 */
    uint32_t isUseDma;        /*!< Enable=RX/TX使用DMA传输 DISABLE=不使用DMA */
} ST_USART_INFO;

/*
 * 标准计算公式：BAUD = PCLK / (16 * DIV)，即 DIV = PCLK / (16 * BAUD)
 * 为了方便计算小数部分，先给分母乘以100，计算完之后再除回去
 * 即 DIV = (PCLK * 100) / (16 * BAUD) = (PCLK * 25) / (4 * BAUD)
 */
#define UART_DIV_SAMPLING16(_PCLK_, _BAUD_)            (((_PCLK_) * 25U) / (4U * (_BAUD_))) // 分母乘以100计算
/* （DIV * 100）的结果直接除以100，得到整数部分 */
#define UART_DIVMANT_SAMPLING16(_PCLK_, _BAUD_)        (UART_DIV_SAMPLING16((_PCLK_), (_BAUD_)) / 100U)
/* 
 * 根据手册，小数部分取值 = 小数部分 * 16，故计算公式如下
 * 1. 先计算小数部分，即用 ((整数 + 小数) * 100) 的值减去 (整数 * 100)，得到 (小数 * 100) 部分
 * 2. 根据公式，将小数部分乘以16，得到需要写入寄存器的值，由于这里乘了100，所以再考虑到四舍五入，= ((小数 * 100) * 16) + 50
 * 3. 最终值再除以100，就得到了最终要写入到寄存器的值regVal
 * 4. 由于小数寄存器只有0~F，故乘以16之后可能会溢出，这部分要加到整数部分里去，即 溢出部分=regVal & 0xF0，小数寄存器部分=regVal & 0x0F
 */
#define UART_DIVFRAQ_SAMPLING16(_PCLK_, _BAUD_)        (((UART_DIV_SAMPLING16((_PCLK_), (_BAUD_)) - (UART_DIVMANT_SAMPLING16((_PCLK_), (_BAUD_)) * 100U)) * 16U + 50U) / 100U)
/* UART BRR = mantissa + overflow + fraction
            = (UART DIVMANT << 4) + (UART DIVFRAQ & 0xF0) + (UART DIVFRAQ & 0x0FU) */
#define UART_BRR_SAMPLING16(_PCLK_, _BAUD_)            (((UART_DIVMANT_SAMPLING16((_PCLK_), (_BAUD_)) << 4U) + \
                                                        (UART_DIVFRAQ_SAMPLING16((_PCLK_), (_BAUD_)) & 0xF0U)) + \
                                                        (UART_DIVFRAQ_SAMPLING16((_PCLK_), (_BAUD_)) & 0x0FU))

#endif